package com.bt7274.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bt7274.mapper.SettingMapper;
import com.bt7274.pojo.Setting;
import com.bt7274.service.SettingService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;

/**
 * @Data 2025/5/28 16:01
 * @Author hp
 * @Version 1.0
 * @Description SettingServiceImpl
 */
@Service
@Slf4j
public class SettingServiceImpl implements SettingService {
    @Resource
    private SettingMapper settingMapper;

    @Resource
    private ObjectMapper objectMapper;

    @Override
    @Transactional
    public <T> T get(@NotNull String configKey, @NotNull Class<T> clazz){
        Setting config = settingMapper.selectOne(
                new QueryWrapper<Setting>().eq("setting_key", configKey)
        );
        if (config != null) {
            String data = config.getSettingValue();
            try {
                return objectMapper.readValue(data, clazz);
            } catch (JsonProcessingException e) {
                log.error("Unable to deserialize setting object: {} -> {}", configKey, data, e);
                throw new RuntimeException(e);
            }
        } else {
            log.error("The configuration key {} doesn't exists in database!", configKey);
            T entity = resolve(clazz);
            if (entity == null) log.error("No Site Configuration!");
            try {
                config = new Setting();
                config.setSettingKey(configKey);
                config.setSettingValue(objectMapper.writeValueAsString(entity));
                settingMapper.insert(config);
                log.info("Resolved missing configuration key via #spawnDefault static method.");
            } catch (JsonProcessingException e) {
                log.error("Unable to serialize setting object: {} -> {}", configKey, entity, e);
                throw new RuntimeException(e);
            }
            return entity;
        }
    }

    @Nullable
    private <T> T resolve(Class<T> clazz) {
        try {
            Method method = clazz.getDeclaredMethod("spawnDefault");
            return (T) method.invoke(null);
        } catch (Throwable e) {
            log.error("Failed to resolve {}", clazz.getName(), e);
            return null;
        }
    }
}
